package com.xxg.renrenproduct.service;

import com.alibaba.fastjson.JSON;
import com.xxg.renrencommon.domain.filedenum.RedisKeyEnum;
import com.xxg.renrencommon.domain.result.BaseResult;
import com.xxg.renrencommon.domain.result.PageInfoResult;
import com.xxg.renrencommon.exception.ProductManagerException;
import com.xxg.renrenproduct.component.ProductComponent;
import com.xxg.renrenproduct.dao.UploadGoodsInfoDao;
import com.xxg.renrenproduct.dao.bean.UploadGoodsInfo;
import com.xxg.renrenproduct.domain.query.DeleteProductQuery;
import com.xxg.renrenproduct.domain.query.GetUploadInfoQuery;
import com.xxg.renrenproduct.domain.query.GoodsInfo;
import com.xxg.renrenproduct.util.RedisUtil;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;

/**
 * 类说明
 *
 * @author szj
 * @date 2021/12/27
 */
@Service
@AllArgsConstructor
public class ProductServiceImpl implements ProductService{
    private final static Logger log = LoggerFactory.getLogger(ProductServiceImpl.class);
    private final ProductComponent productComponent;
    private final UploadGoodsInfoDao uploadGoodsInfoDao;
    private final RedisUtil redisUtil;
    private final static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(5, 10, 120, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), (r) -> {
        Thread thread = new Thread(r);
        thread.setName("upload_");
        return thread;
    }, new ThreadPoolExecutor.CallerRunsPolicy());

    @Override
    public BaseResult<Map<String, String>> upload(MultipartFile file) throws IOException {
        byte[] bytes = file.getBytes();
        String goodsStr = new String(bytes);
        List<GoodsInfo> goodsInfos = JSON.parseArray(goodsStr, GoodsInfo.class);
        final String batch = goodsInfos.get(0).getThumb().split("/")[3];
        Boolean absent = redisUtil.setIfAbsent(String.format(RedisKeyEnum.UPLOAD_PRODUCT_KEY.key(), batch), batch, RedisKeyEnum.UPLOAD_PRODUCT_KEY.time());
        if (!absent) {
            return new BaseResult<>("该批次正在处理", null);
        }
        UploadGoodsInfo info = uploadGoodsInfoDao.findById(batch);
        if (info != null) {
            return new BaseResult<>("已上传过该批次", null);
        }
        EXECUTOR.execute(() -> {
            final List<GoodsInfo> errorGoodsInfos = new CopyOnWriteArrayList<>();
            final List<String> errorMessage = new CopyOnWriteArrayList<>();
            final List<Integer> ids = new CopyOnWriteArrayList<>();
            for (GoodsInfo goodsInfo : goodsInfos) {
                try {
                    Integer id = productComponent.insertProduct(goodsInfo);
                    ids.add(id);
                } catch (ProductManagerException e) {
                    log.error("导入出错" + e.getMessage(), e);
                    log.info("出错数据：{}", JSON.toJSONString(goodsInfo));
                    errorMessage.add(e.getErrorMessage());
                    errorGoodsInfos.add(goodsInfo);
                    return;
                }
                log.info("成功数据：{}", JSON.toJSONString(goodsInfo));
            }
            if (goodsInfos.size() > 0) {
                UploadGoodsInfo uploadGoodsInfo = new UploadGoodsInfo();
                uploadGoodsInfo.setId(batch);
                uploadGoodsInfo.setErrorMessage(JSON.toJSONString(errorMessage));
                uploadGoodsInfo.setErrorData(JSON.toJSONString(errorGoodsInfos));
                uploadGoodsInfo.setUploadIds(ids);
                uploadGoodsInfoDao.insert(uploadGoodsInfo);
            }
            redisUtil.del(String.format(RedisKeyEnum.UPLOAD_PRODUCT_KEY.key(), batch));
        });
        return new BaseResult<>();
    }

    @Override
    public BaseResult<Void> delete(DeleteProductQuery query) {
        UploadGoodsInfo info = uploadGoodsInfoDao.findById(query.getBatch());
        List<Integer> ids = info.getUploadIds();
        if (ids == null) {
            return new BaseResult<>("未找到对应批次", null);
        }
        ids.forEach(id -> {
            try {
                productComponent.deleteGoodsByGoodsId(id);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                log.info("删除出错id：{}", id);
            }
        });
        return new BaseResult<>();
    }

    @Override
    public BaseResult<PageInfoResult<UploadGoodsInfo>> getUploadInfo(GetUploadInfoQuery query) {
        List<UploadGoodsInfo> uploadGoodsInfos = uploadGoodsInfoDao.findList(query.getId(), query.getCreateTimeStart(), query.getCreateTimeEnd(), query.getPageNo(), query.getPageSize());
        long count = uploadGoodsInfoDao.countList(query.getId(), query.getCreateTimeStart(), query.getCreateTimeEnd());
        PageInfoResult<UploadGoodsInfo> tPageInfoResult = new PageInfoResult<>(count, uploadGoodsInfos);
        return new BaseResult<>(tPageInfoResult);
    }
}
